package org.javaongems.client.vcl;

import java.util.List;

import org.javaongems.client.rt.awt.Rectangle;
import org.javaongems.client.rt.util.ArrayUtils;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;

/**
 * Alignment rules:
 *  - TOP
 *  	* <height: xx>; position: relative; top: 0px; width: auto; 
 *  - LEFT
 *  	* <width: xx>; height: 100%; float: left;
 *  - RIGHT
 *  	* <width: xx>; height: 100%; float: right;
 *  - BOTTOM
 *  	* <height: xx>; width: 100%; position: absolute; bottom: 0px; [left: 0px];
 *  - CLIENT
 *  	* width: 100%; height: 100%;
 *  - NONE
 *  	* left: 20px; top: 20px; position: absolute;
 * 
 * @author Ashin Wimalajeewa (ash)
 * 
 * TODO: currently only one control can be aligned with bottom. all other bottom 
 * references will be lost.
 * TODO: auto-wire hints/tooltips to autoshow
 * TODO: add PopupMenu property support
 */
public class Control extends Component implements EventListener {
	final static public int ALIGN_NONE = 0;
	final static public int ALIGN_TOP = 1;
	final static public int ALIGN_BOTTOM = 2;
	final static public int ALIGN_LEFT = 3;
	final static public int ALIGN_RIGHT = 4;
	final static public int ALIGN_CLIENT = 5;

	final static public int TEXT_ALIGNMENT_LEFT = 0;
	final static public int TEXT_ALIGNMENT_RIGHT = 1;
	final static public int TEXT_ALIGNMENT_CENTER = 2;
	final static public int TEXT_ALIGNMENT_JUSTIFY = 3;
	
	final static public int DIMENSION_100 = -1;		// eg. height: 100%;
	final static public int DIMENSION_AUTO = -2;	// eg. height: auto;
	
	final static public int DM_MANUAL = 0;
	final static public int DM_AUTO = 1;
	
	final static public String ALIGN_PROP = "align";
	final static public String WIDTHHEIGHT_PROP = "width-height";
	final static public String AUTOSIZE_PROP = "auto-size";
	final static public String CAPTION_PROP = "caption";
	final static public String COLOR_PROP = "color";
	final static public String CURSOR_PROP = "cursor";
	final static public String DRAGMODE_PROP = "drag-mode";
	final static public String ENABLED_PROP = "enabled";
	final static public String FONT_PROP = "font";
	final static public String HINT_PROP = "hint";
	final static public String PARENTCOLOR_PROP = "parent-color";
	final static public String PARENTFONT_PROP = "parent-font";
	final static public String PARENTSHOWHINT_PROP = "parent-show-hint";
	final static public String TEXT_PROP = "text";
	final static public String VISIBLE_PROP = "visible";
	
	protected int align = ALIGN_NONE;
	protected boolean autoSize = false;
	protected String caption = "";
	protected String color = "";
	protected String cursor = "default";
	protected int dragMode = DM_MANUAL;
	protected boolean enabled = true;
	protected String font = "";
	protected String hint = "";
	protected boolean parentColor = true;
	protected boolean parentFont = true;
	protected boolean parentShowHint = true;
	protected boolean showHint = false;
	protected String text = "";
	protected boolean visible = true;
	
	protected ControlDomRenderer domRenderer;
	protected ControlListener listener;
	
	public Control() {
		domRenderer = createDomRender();
		domRenderer.setControl(this);
	}
	
	// overrides
	public void setParentComponent(Component prnt) {
		setParent((Control) prnt);
	}
	
	public void setParent(Control prnt) {
		Control parentAsCtrl = (Control) parent;
		if (parentAsCtrl == prnt)
			return;
		if (parentAsCtrl != null)
			parentAsCtrl.disown(this);
		super.setParentComponent(prnt);
		prnt.adopt(this);
	}
	
	protected void adopt(Control child) {
		insertComponent(child);
		invalidate(); // repaint();
	}
	
	protected void disown(Control child) {
		removeComponent(child);
		invalidate(); // repaint();
	}
	
	public Control getParent() {
		return (Control) getParentComponent();
	}
	
	public boolean isRootAncestor() {
		Component par = getParentComponent();
		return (par == null || par == this);
	}
	
	public void setTop(int t) { 
		super.setTop(t); 
		paintFrameTop();
	};
	
	public void setLeft(int l) { 
		super.setLeft(l);
		paintFrameLeft();
	};

	protected void destroyed() {
		domRenderer.resetElement();
		domRenderer.setElement(null);
		domRenderer = null;
		listener = null;
		super.destroyed();
	}
	
	// control
	public int getControlIndex() {
		Control prnt = getParent();
		if (prnt == null)
			return 0;
		return prnt.getControls().indexOf(this);
	}
	
	public boolean setControlIndex(int index) {
		Control parentCtrl = getParent(); 
		List lst = parentCtrl.getControls();
		int curr = lst.indexOf(this);
		if (curr == index)
			return false;
		Control ctrlAtIdx = (Control) lst.get(index);
		lst.remove(this);
		lst.add(index, this);
		int cmpAtIdx = ctrlAtIdx.getComponentIndex();
		this.setComponentIndex(cmpAtIdx);
		parentCtrl.invalidate();
		return true;
	}
	
	public List getControls() {
		return null;
	}
	
	public int getControlCount() {
		return 0;
	}
	
	public void invalidate() {
		ControlInvalidation.add(this);
	}
	
	public void refresh() {
		repaint();
	}
	
	public void repaint() {
		if (!isReadyToPaint())
			return;
		initialiseDomElement();
		paint();
	}

	protected void initialiseDomElement() {
		if (isLoading())
			return;
		domRenderer.resetElement();
		Element domElement = domRenderer.element;
		if (domElement == null)
			domElement = createElement();
		setElement(domElement);
		Control prnt = getParent();
		if (prnt != null) {
			Element prntElem = prnt.getElement();	
			if (prntElem != null)
				domRenderer.setParentElement(prntElem);
		}
	}

	public void paint() {
		if (!isReadyToPaint())
			return;
		recalcClientRectAndUpdateClientChild();
		paintFrame();
		paintChildren();
	}
	
	protected boolean isCanvasReady() {
		Control prnt = getParent();
		return !(prnt == null || prnt.getElement() == null);
	}
	
	protected boolean isReadyToPaint() {
		return isCanvasReady() && !isLoading();
	}

	protected void paintChildren() {
		// only wincontrols are composites
	}
	
	protected void paintChildrenZorder() {
		// only wincontrols are composites
	}
	
	protected boolean paintFrame() {
		if (!isReadyToPaint())
			return false;
		paintFrameParentOverrides();
		paintFrameStruts();
		paintFramePosition();
		paintFrameDimension();
		paintAttributeCaption();
		paintAttributeText();
		paintAttributeAlignment();
		paintAttributeAutoSizing();
		paintAttributeCursor();
		paintAttributeEnabled();
		paintAttributeVisible();
		return true;
	}
	
	protected void paintFrameStruts() {
		// only valid for forms
	}

	protected void paintFramePosition() {
		if (!isReadyToPaint())
			return;
		paintFrameTop();
		paintFrameLeft();
	}

	protected void paintFrameTop() {
		if (!isReadyToPaint())
			return;
		domRenderer.setTopPosition(getTop());
	}

	protected void paintFrameLeft() {
		if (!isReadyToPaint())
			return;
		domRenderer.setLeftPosition(getLeft());
	}

	protected void paintFrameDimension() {
		if (!isReadyToPaint())
			return;
		paintFrameWidth();
		paintFrameHeight();
	}

	protected void paintFrameWidth() {
		if (!isReadyToPaint())
			return;
		domRenderer.setPixelWidth(boundsRect.width);
	}
	
	protected void paintFrameHeight() {
		if (!isReadyToPaint())
			return;
		domRenderer.setPixelHeight(boundsRect.height);
	}

	protected void paintAttributeAlignment() {
		if (!isReadyToPaint())
			return;
		domRenderer.setAlignment(align);
	}

	protected void paintAttributeAutoSizing() {
		if (!isReadyToPaint())
			return;
		domRenderer.setAutoSizing(autoSize);
	}

	protected void paintFrameParentOverrides() {
		if (!isReadyToPaint())
			return;
		paintParentConditionalColor();
		paintParentConditionalFont();
		paintParentConditionalHint();
	}

	protected void paintParentConditionalHint() {
		if (!isReadyToPaint())
			return;
		boolean showHint = false;
		if (!parentShowHint)
			showHint = true;
		else {
			Control theParent = this.getParent();
			while (theParent != null && theParent.isParentShowHint()) {
				if (theParent.isRootAncestor())
					break;
				theParent = theParent.getParent();
			}
			if (theParent != null)
				showHint = theParent.isParentShowHint();
		}
		if (showHint)
			domRenderer.setTitle(hint);
	}

	protected void paintParentConditionalFont() {
		if (!isReadyToPaint())
			return;
		String fntToUse = "";
		if (!parentFont)
			fntToUse = font;
		else {
			Control theParent = this.getParent();
			while (theParent != null && theParent.isParentFont()) {
				if (theParent.isRootAncestor())
					break;
				theParent = theParent.getParent();
			}
			if (theParent != null)
				fntToUse = theParent.getFont();
		}
		domRenderer.setFont(fntToUse);
	}

	protected void paintParentConditionalColor() {
		if (!isReadyToPaint())
			return;
		String clrToUse = "";
		if (!parentColor)
			clrToUse = color;
		else {
			Control theParent = this.getParent();
			while (theParent != null && theParent.isParentColor()) {
				if (theParent.isRootAncestor())
					break;
				theParent = theParent.getParent();
			}
			if (theParent != null)
				clrToUse = theParent.getColor();
		}
		domRenderer.setBackgroundColor(clrToUse);
	}

	protected void paintAttributeCursor() {
		if (!isReadyToPaint())
			return;
		domRenderer.setCursor(cursor);
	}

	public void setControlListener(ControlListener lsnr) {
		listener = lsnr;
	}
	
	protected ControlDomRenderer createDomRender() {
		return new ControlDomRenderer();
	}
	
	protected Element createElement() {
		Element elm = DOM.createDiv();
		return elm;
	}

	public Element getElement() {
		return domRenderer.element;
	}
	
	public boolean setElement(Element elm) {
		boolean ret = domRenderer.setElement(elm);
		if (ret)
			setSinkEvents();
		return ret;
	}

	protected void setSinkEvents() {
		domRenderer.sinkEvents(getSinkEvents());
	}
	
	protected int getSinkEvents() {
		return Event.MOUSEEVENTS | Event.ONCLICK | Event.ONDBLCLICK;
	}
	
	public void onBrowserEvent(Event event) {
		ControlEvent.setControlEvent(event);
		/*
		if (ControlEvent.eventType == Event.ONCLICK) {
			System.out.println("clicked: " + this);
		} else if (ControlEvent.eventType == Event.ONKEYPRESS) {
			System.out.println("pressed: " + this);
		} else if (ControlEvent.eventType == Event.ONFOCUS) {
//			bringToFront();
			System.out.println("focused: " + this);
		}
		*/
		boolean doControlEvent = false, doInternalControlEvent = false;
		if (ControlEvent.targetControl != null) {
			if (listener != null) 
				doControlEvent = true;
		} else 
			doInternalControlEvent = true;
		ControlEvent.initialiseInfo();
		try {
			if (doControlEvent)
				onControlEvent();
			else if (doInternalControlEvent)
				onInternelControlEvent(ControlEvent.targetElement);
		} finally {
			ControlEvent.clearInfo();
		}
	}
	
	public void beginDrag(boolean immediate, int threshold) {
		ControlEvent.beginDrag(immediate, threshold);
	}
	
	protected void doStartDrag() {
		if (listener != null)
			listener.onStartDrag(this);
	}
	
	protected void doEndDrag() {
		if (listener != null) {
			doDragDrop();
			listener.onEndDrag(this, ControlEvent.targetControl, ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y]);
		}
	}
	
	protected void doDragDrop() {
		if (listener != null) {
			if (ControlEvent.dragDropAccepted) 
				listener.onDragDrop(this, ControlEvent.targetControl, ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y]);
		}		
	}
	
	protected void doDragOver(int dragState) {
		if (listener != null)
			ControlEvent.dragDropAccepted = listener.onDragOver(this, ControlEvent.targetControl, ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y], dragState);
	}
	
	protected boolean onControlEvent() {
	    switch (ControlEvent.eventType) {
	      case Event.ONCLICK: listener.onClick(this); break;
	      case Event.ONDBLCLICK: 	listener.onDblClick(this); break;
	      case Event.ONMOUSEDOWN: 	listener.onMouseDown(this, ControlEvent.listenerInfo[ControlEvent.LI_MOUSE], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT], ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y]); break;
	      case Event.ONMOUSEMOVE: 	listener.onMouseMove(this, ControlEvent.listenerInfo[ControlEvent.LI_MOUSE], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT], ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y]); break;
	      case Event.ONMOUSEUP: 	listener.onMouseUp(this, ControlEvent.listenerInfo[ControlEvent.LI_MOUSE], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT], ControlEvent.listenerInfo[ControlEvent.LI_X], ControlEvent.listenerInfo[ControlEvent.LI_Y]); break;
		default:
			return false;
	    }
	    return true;
	}
	
	protected boolean onInternelControlEvent(Element elm) {
		return false;
	}
	
	protected Control getClientChild() {
		// only wincontrols are composites
		return null;
	}
	
	protected void setClientChild(Control child) {
		// only wincontrols are composites
	}
	
	protected void recalcClientRectAndUpdateClientChild() {
		// only wincontrols are composites
	}
	
	// derived properties
	public int getClientWidth() {
		return boundsRect.width;
	}
	
	public int getClientHeight() {
		return boundsRect.height;
	}
	
	public Rectangle getClientRect() {
		return boundsRect;
	}

	// published properties
	public int getAlign() {
		return align; 
	}
	
	public void setAlign(int al) {
		if (align == al)
			return;
		int origAlign = align;
		align = al;
		paintAttributeAlignment();
		Control parentCtl = getParent();
		if (parentCtl != null) {
			if (origAlign == ALIGN_CLIENT)
				parentCtl.setClientChild(null);
			if (align == ALIGN_CLIENT) {
				Control currClientChild = parentCtl.getClientChild();
				if (currClientChild != null)
					currClientChild.setAlign(ALIGN_NONE);
				parentCtl.setClientChild(this);
			}
			if (align != ALIGN_NONE)
				parentCtl.recalcClientRectAndUpdateClientChild();
		}
	}
	
	public boolean isAutoSize() {
		return autoSize;
	}
	
	public void setAutoSize(boolean auto) {
		if (autoSize == auto)
			return;
		autoSize = auto;
		paintAttributeAutoSizing();
	}
	
	public void setCaption(String cap) {
		if (caption == cap || caption.equals(cap))
			return;
		caption = cap;
		paintAttributeCaption();
	}

	protected void paintAttributeCaption() {
		if (!isReadyToPaint())
			return;
		domRenderer.setCaption();
	}
	
	public String getCaption() {
		return caption;
	}
	
	public void setColor(String clr) {
		if (color == clr || color.equals(clr))
			return;
		color = clr;
		paintParentConditionalColor();
	}
	
	public String getColor() {
		return color;
	}
	
	public void setCursor(String csr) {
		if (cursor == csr || cursor.equals(csr))
			return;
		cursor = csr;
		paintAttributeCursor();
	}
	
	public String getCursor() {
		return cursor;
	}
	
	public void setDragMode(int dm) {
		dragMode = dm;
	}
	
	public int getDragMode() {
		return dragMode;
	}
	
	public void setEnabled(boolean e) {
		if (enabled == e)
			return;
		enabled = e;
		paintAttributeEnabled();
	}

	protected void paintAttributeEnabled() {
		if (!isReadyToPaint())
			return;
		domRenderer.setEnabled(enabled);
	}
	
	public boolean isEnabled() {
		return enabled;
	}
	
	public void setFont(String f) {
		if (font == f || font.equals(f))
			return;
		font = f;
		paintParentConditionalFont();
	}
	
	public String getFont() {
		return font;
	}
	
	public void setHint(String h) {
		if (hint == h || hint.equals(h))
			return;
		hint = h;
		paintParentConditionalHint();
	}
	
	public String getHint() {
		return hint;
	}
	
	public void setParentColor(boolean pc) {
		if (parentColor == pc)
			return;
		parentColor = pc;
		paintParentConditionalColor();
	}
	
	public boolean isParentColor() {
		return parentColor;
	}
	
	public void setParentFont(boolean pf) {
		if (parentFont == pf)
			return;
		parentFont = pf;
		paintParentConditionalFont();
	}
	
	public boolean isParentFont() {
		return parentFont;
	}

	public void setParentShowHint(boolean psh) {
		if (parentShowHint == psh)
			return;
		parentShowHint = psh;
		paintParentConditionalHint();
	}
	
	public boolean isParentShowHint() {
		return parentShowHint;
	}
	
	public void setText(String t) {
		if (text == t || text.equals(t))
			return;
		text = t;
		paintAttributeText();
	}

	protected void paintAttributeText() {
		if (!isReadyToPaint())
			return;
		domRenderer.setText();
	}
	
	public String getText() {
		return text;
	}
	
	public void setVisible(boolean v) {
		if (visible == v)
			return;
		visible = v;
		paintAttributeVisible();
	}
	
	public void bringToFront() {
		Control prnt = getParent();
		int front = prnt.getControlCount();
		setControlIndex(front -1);
	}
	
	public void sendToBack() {
		Control prnt = getParent();
		setControlIndex(0);
	}
	
	protected void paintAttributeVisible() {
		if (!isReadyToPaint())
			return;
		domRenderer.setVisible(visible);
	}
	
	protected void paintAttributeZindex() {
		if (!isReadyToPaint())
			return;
		int zIndex = getControlIndex();
		domRenderer.setZindex(zIndex);
	}

	public boolean isVisible() {
		return visible;
	}
	
	public void setWidth(int w) {
		boolean ok = true;
		if (!isLoading()) {
			if (listener != null)
				ok = listener.onCanResize(this, w, boundsRect.height);
		}
		if (ok) {
			boundsRect.width = w;
			paintFrameWidth();
			if (!isLoading() && listener != null)
				listener.onResize(this);
		}
	}

	public void setHeight(int h) {
		boolean ok = true;
		if (!isLoading()) {
			if (listener != null)
				ok = listener.onCanResize(this, boundsRect.width, h);
		}
		if (ok) {
			boundsRect.height = h;
			paintFrameHeight();
			if (!isLoading() && listener != null)
				listener.onResize(this);
		}
	}
	
	public Rectangle getBoundsRect() {
		return boundsRect;
	}
	
	public void setBoundsRect(Rectangle r) {
		if (boundsRect.equals(r))
			return;
		setLeft(r.x);
		setTop(r.y);
		boolean resized = false;
		if (boundsRect.width != r.width) {
			setWidth(r.width);
			resized = true;
		}
		if (boundsRect.height != r.height) {
			setHeight(r.height);
			resized = true;
		}
		if (resized)
			recalcClientRectAndUpdateClientChild();
	}
	
	public int getWidth() {
		return boundsRect.width;
	}
	
	public int getHeight() {
		return boundsRect.height;
	}
	
	protected void writeProperties(PropertiesWriter wrtr) {
		writeAlignProperty(wrtr);
		writeWidthHeightProperties(wrtr);
		writeAutoSizeProperty(wrtr);
		writeCaptionProperty(wrtr);
		writeColorProperty(wrtr);
		writeCursorProperty(wrtr);
		writeDragModeProperty(wrtr);
		writeEnabledProperty(wrtr);
		writeFontProperty(wrtr);
		writeHintProperty(wrtr);
		writeParentColorProperty(wrtr);
		writeParentFontProperty(wrtr);
		writeParentShowHintProperty(wrtr);
		writeTextProperty(wrtr);
		writeVisibleProperty(wrtr);
	}

	protected void writeAlignProperty(PropertiesWriter wrtr) {
		if (align != ALIGN_NONE)
			wrtr.writeNumber(ALIGN_PROP, align);
	}
	
	protected void writeWidthHeightProperties(PropertiesWriter wrtr) {
		if (!isDefaultWidthHeight())
			writeDelimitedProperties(new int[] {boundsRect.width,boundsRect.height}, WIDTHHEIGHT_PROP, wrtr);
	}
	
	protected boolean isDefaultWidthHeight() {
		return boundsRect.width == 0 && boundsRect.height == 0;
	}

	protected void writeAutoSizeProperty(PropertiesWriter wrtr) {
		if (autoSize)
			wrtr.writeBoolean(AUTOSIZE_PROP, autoSize);
	}

	protected void writeCaptionProperty(PropertiesWriter wrtr) {
		if (!"".equals(caption))
			wrtr.writeString(CAPTION_PROP, caption);
	}

	protected void writeColorProperty(PropertiesWriter wrtr) {
		if (!"".equals(color))
			wrtr.writeString(COLOR_PROP, color);
	}

	protected void writeCursorProperty(PropertiesWriter wrtr) {
		if (!"default".equals(cursor))
			wrtr.writeString(CURSOR_PROP, color);
	}

	protected void writeDragModeProperty(PropertiesWriter wrtr) {
		if (dragMode != DM_MANUAL)
			wrtr.writeNumber(DRAGMODE_PROP, dragMode);
	}

	protected void writeEnabledProperty(PropertiesWriter wrtr) {
		if (!enabled)
			wrtr.writeBoolean(ENABLED_PROP, enabled);
	}

	protected void writeFontProperty(PropertiesWriter wrtr) {
		if (!"".equals(font))
			wrtr.writeString(FONT_PROP, font);
	}

	protected void writeHintProperty(PropertiesWriter wrtr) {
		if (!"".equals(hint))
			wrtr.writeString(HINT_PROP, hint);
	}

	protected void writeParentColorProperty(PropertiesWriter wrtr) {
		if (!parentColor)
			wrtr.writeBoolean(PARENTCOLOR_PROP, parentColor);
	}

	protected void writeParentFontProperty(PropertiesWriter wrtr) {
		if (!parentFont)
			wrtr.writeBoolean(PARENTFONT_PROP, parentFont);
	}

	protected void writeParentShowHintProperty(PropertiesWriter wrtr) {
		if (!parentShowHint)
			wrtr.writeBoolean(PARENTSHOWHINT_PROP, parentShowHint);
	}

	protected void writeTextProperty(PropertiesWriter wrtr) {
		if (!"".equals(text))
			wrtr.writeString(TEXT_PROP, text);
	}

	protected void writeVisibleProperty(PropertiesWriter wrtr) {
		if (!visible)
			wrtr.writeBoolean(VISIBLE_PROP, visible);
	}

	protected void readProperties(PropertiesReader rdr) {
		setAlign((int) rdr.readNumber(ALIGN_PROP, ALIGN_NONE));
		readWidthHeightProperties(rdr);
		setAutoSize(rdr.readBoolean(AUTOSIZE_PROP, false));
		setCaption(rdr.readString(CAPTION_PROP, ""));
		setColor(rdr.readString(COLOR_PROP, ""));
		setCursor(rdr.readString(CURSOR_PROP, "default"));
		setDragMode((int) rdr.readNumber(DRAGMODE_PROP, DM_MANUAL));
		setEnabled(rdr.readBoolean(ENABLED_PROP, true));
		setFont(rdr.readString(FONT_PROP, ""));
		setHint(rdr.readString(HINT_PROP, ""));
		setParentColor(rdr.readBoolean(PARENTCOLOR_PROP, true));
		setParentFont(rdr.readBoolean(PARENTFONT_PROP, true));
		setParentShowHint(rdr.readBoolean(PARENTSHOWHINT_PROP, true));
		setText(rdr.readString(TEXT_PROP, ""));
		setVisible(rdr.readBoolean(VISIBLE_PROP, true));
	}
	
	protected void readWidthHeightProperties(PropertiesReader pr) {
		String widthHeight = pr.readString(WIDTHHEIGHT_PROP, null);
		if (widthHeight != null) {
			int[] dim = ArrayUtils.parseIntArray(widthHeight, ArrayUtils.COMMA_DELIM);
			setWidth(dim[0]);
			setHeight(dim[1]);
		}
	}
}
